//
//  StringExample.swift
//  SwiftCode
//
//  Created by 于虎拴 on 2023/2/28.
//

import UIKit

class StringExample: ListViewController {
  deinit {
    print(#file, #function)
  }
  
  override func getItemCount() -> Int {
    data.count
  }
  
  override func getItem(_ indexPath: IndexPath) -> ListViewController.Item {
    data[indexPath.row]
  }
  
  private lazy var data: [Item] = [
    .init(title: "ValueType", description: "值类型", action: valueType),
    .init(title: "Characters", description: "使用字符", action: characters),
    .init(title: "Concatenating", description: "连接字符串和字符", action: concatenating),
    .init(title: "Interpolation", description: "字符串插值", action: interpolation),
    .init(title: "Unicode", description: "标量值 & 扩展字素簇", action: unicode),
    .init(title: "Counting", description: "字符计数", action: counting),
    .init(title: "Accessing", description: "访问和修改", action: accessing),
    .init(title: "Substrings", description: "子字符串", action: substrings),
    .init(title: "Comparing", description: "字符串比较", action: comparing),
    .init(title: "UnicodeRepresentations", description: "Unicode 表示", action: unicodeRepresentations),
  ]
}

private func valueType() {
  let string1 = "hello"
  var string2 = string1
  
  print(string1)
  print(string2)
  string2 += " world!"
  
  print(string1)
  print(string2)
}

private func characters() {
  for character in "Dog!🐶" {
    print(character)
  }
  let exclamationMark: Character = "!"
  print(exclamationMark)
  
  let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
  let catString = String(catCharacters)
  print(catString)
  // Prints "Cat!🐱"
}

private func concatenating() {
  let string1 = "hello"
  let string2 = " there"
  var welcome = string1 + string2
  // welcome now equals "hello there"
  print(welcome)
  
  let exclamationMark: Character = "!"
  welcome.append(exclamationMark)
  // welcome now equals "hello there!"
  print(welcome)
}

private func interpolation() {
  let multiplier = 3
  let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
  // message is "3 times 2.5 is 7.5"
  print(message)
  
  print(#"Write an interpolated string in Swift using \(multiplier)."#)
  // Prints "Write an interpolated string in Swift using \(multiplier)."
  
  print(#"6 times 7 is \#(6 * 7)."#)
  // Prints "6 times 7 is 42."
}

private func unicode() {
  let eAcute: Character = "\u{E9}"                         // é
  let combinedEAcute: Character = "\u{65}\u{301}"          // e followed by
  // eAcute is é, combinedEAcute is é
  print(eAcute)
  print(combinedEAcute)
  
  let precomposed: Character = "\u{D55C}"                  // 한
  let decomposed: Character = "\u{1112}\u{1161}\u{11AB}"   // ᄒ, ᅡ, ᆫ
  print(precomposed)
  print(decomposed)
  
  let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
  // regionalIndicatorForUS is 🇺🇸
  print(regionalIndicatorForUS)
}

private func counting() {
  var word = "cafe"
  print("the number of characters in \(word) is \(word.count)")
  // Prints "the number of characters in cafe is 4"
  
  word += "\u{301}"    // COMBINING ACUTE ACCENT, U+0301
  
  print("the number of characters in \(word) is \(word.count)")
  // Prints "the number of characters in café is 4"
}

private func accessing() {
  let greeting = "Guten Tag!"
  print(greeting[greeting.startIndex])
  // G
  
  print(greeting[greeting.index(before: greeting.endIndex)])
  // !
  
  print(greeting[greeting.index(after: greeting.startIndex)])
  // u
  
  let index = greeting.index(greeting.startIndex, offsetBy: 7)
  print(greeting[index])
  // a
  
  // 使用 indices 属性访问字符串中单个字符的所有索引
  for index in greeting.indices {
    print("\(greeting[index]) ", terminator: "")
  }
  // Prints "G u t e n   T a g ! "
  
  // 插入和移除
  var welcome = "hello"
  welcome.insert("!", at: welcome.endIndex)
  // welcome now equals "hello!"
  print(welcome)
  
  welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
  // welcome now equals "hello there!"
  print(welcome)
  
  welcome.remove(at: welcome.index(before: welcome.endIndex))
  // welcome now equals "hello there"
  print(welcome)
  
  let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
  welcome.removeSubrange(range)
  // welcome now equals "hello"
  print(welcome)
}

private func substrings() {
  let greeting = "Hello, world!"
  let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
  let beginning = greeting[..<index]
  // beginning is "Hello"
  print(beginning)
  
  // Convert the result to a String for long-term storage.
  let newString = String(beginning)
  print(newString)
}

private func comparing() {
  // ==
  let quotation = "We're a lot alike, you and I."
  let sameQuotation = "We're a lot alike, you and I."
  if quotation == sameQuotation {
    print("These two strings are considered equal")
  }
  // Prints "These two strings are considered equal"
  
  // 字素簇
  // "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
  let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
  
  // "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
  let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
  
  if eAcuteQuestion == combinedEAcuteQuestion {
    print("These two strings are considered equal")
  }
  // Prints "These two strings are considered equal"
  
  // 英语中使用的拉丁文大写字母 A（U+0041 或“A”）不等同于俄语中使用的西里尔大写字母 A（U+0410 或“А”）
  let latinCapitalLetterA: Character = "\u{41}"
  
  let cyrillicCapitalLetterA: Character = "\u{0410}"
  
  if latinCapitalLetterA != cyrillicCapitalLetterA {
    print(latinCapitalLetterA)
    print(cyrillicCapitalLetterA)
    print("These two characters aren't equivalent.")
  }
  // Prints "These two characters aren't equivalent."
  
  // 前缀和后缀相等
  let romeoAndJuliet = [
    "Act 1 Scene 1: Verona, A public place",
    "Act 1 Scene 2: Capulet's mansion",
    "Act 1 Scene 3: A room in Capulet's mansion",
    "Act 1 Scene 4: A street outside Capulet's mansion",
    "Act 1 Scene 5: The Great Hall in Capulet's mansion",
    "Act 2 Scene 1: Outside Capulet's mansion",
    "Act 2 Scene 2: Capulet's orchard",
    "Act 2 Scene 3: Outside Friar Lawrence's cell",
    "Act 2 Scene 4: A street in Verona",
    "Act 2 Scene 5: Capulet's mansion",
    "Act 2 Scene 6: Friar Lawrence's cell"
  ]
  
  var act1SceneCount = 0
  for scene in romeoAndJuliet {
    if scene.hasPrefix("Act 1 ") {
      act1SceneCount += 1
    }
  }
  print("There are \(act1SceneCount) scenes in Act 1")
  // Prints "There are 5 scenes in Act 1"
  
  var mansionCount = 0
  var cellCount = 0
  for scene in romeoAndJuliet {
    if scene.hasSuffix("Capulet's mansion") {
      mansionCount += 1
    } else if scene.hasSuffix("Friar Lawrence's cell") {
      cellCount += 1
    }
  }
  print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
  // Prints "6 mansion scenes; 2 cell scenes"
}

private func unicodeRepresentations() {
  let dogString = "Dog‼🐶"
  for codeUnit in dogString.utf8 {
    print("\(codeUnit) ", terminator: "")
  }
  print("")
  // Prints "68 111 103 226 128 188 240 159 144 182 "
  
  for codeUnit in dogString.utf16 {
    print("\(codeUnit) ", terminator: "")
  }
  print("")
  // Prints "68 111 103 8252 55357 56374 "
  
  // 每个 UnicodeScalar 都有一个 value 属性，它返回标量的 21 位值，用 UInt32 值表示
  for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ", terminator: "")
  }
  print("")
  // Prints "68 111 103 8252 128054 "
}
